"""
Case Type   : tinyblob数据类型
Case Name   : lib驱动连接数据库，支持tinyblob类型相关操作
Create At   : 2022.08.11
Owner       : @zou_jialiang0501129488
Description :
    1、创建b库
    2、b库下查询dolphin插件
    3、使用lib驱动链接数据库并执行命令
    4、清理环境
Expect      :
    1、成功
    2、成功
    3、成功
    4、成功
History     :
    2022/3/30 modify by @zou_jialiang050 环境中无法搜索到头文件，修改用例以适配环境
    modified by zhanghuan96，2024.7.9，适配最新代码
"""

import os
import re
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

sh_primary = CommonSH('PrimaryDbUser')


@unittest.skipIf(2 > sh_primary.get_node_num(), '非1主2备环境不执行')
class DatatypeTest01(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.common = Common()
        self.user_node = Node('PrimaryDbUser')
        self.pri_root_node = Node('PrimaryRoot')
        self.standby2_root_node = Node('Standby2Root')
        self.constant = Constant()
        self.pkg_path = os.path.dirname(macro.DB_SCRIPT_PATH)
        self.db_name = 'db_tinyblob_case47'

    def test_tinyblob(self):
        global scp_path
        scp_path = os.path.join(self.pkg_path, 'include', 'libpq')
        text = '-----step1:创建兼容b库的数据库;expect:成功-----'
        self.log.info(text)
        sql_cmd = f"drop database if exists {self.db_name};" \
                  f"create database {self.db_name} " \
                  f"dbcompatibility ='B' encoding ='UTF8';"
        self.log.info(sql_cmd)
        sql_res = sh_primary.execut_db_sql(sql_cmd, dbname='postgres')
        self.log.info(sql_res)
        self.assertIn(self.constant.CREATE_DATABASE_SUCCESS, sql_res,
                      '执行失败' + text)

        text = '-----step2:b库下查询dolphin插件;expect:自动加载成功,无需手动创建-----'
        self.log.info(text)
        sql_cmd = "select extname from pg_extension where extname ='dolphin';"
        self.log.info(sql_cmd)
        sql_res = sh_primary.execut_db_sql(sql_cmd, dbname=self.db_name)
        self.log.info(sql_res)
        self.assertIn('extname', sql_res, '查询失败')
        self.assertIn('dolphin', sql_res, '执行失败' + text)

        text = '-----step3:使用lib驱动链接数据库并执行命令;expect:成功-----'
        self.log.info(text)
        self.log.info('-----解压libpq文件夹-----')
        result = self.common.get_sh_result(self.standby2_root_node,
                                           f"ls {self.pkg_path}")
        file_name = ''.join(re.findall('openGauss-Libpq.*\.tar\.gz',
                                       result))
        self.log.info(file_name)
        if file_name is not None:
            scp_cmd = f"scp {file_name} root@" \
                      f"{self.pri_root_node.ssh_host}:{self.pkg_path}"
            passwd = self.pri_root_node.ssh_password
            cmd = f'''cd {self.pkg_path}
                  expect <<EOF
                  set timeout 30
                  spawn {scp_cmd}
                  expect {{{{
                      "*yes/no*" {{{{send "yes\n";exp_continue}}}}
                      "*password:" {{{{send "{passwd}\n"}}}}
                  }}}}''' + '\nexpect EOF\n'
            self.common.get_sh_result(self.standby2_root_node, cmd)
            res = self.common.get_sh_result(self.pri_root_node,
                                            f"ls {self.pkg_path}")
            self.assertIn(file_name, res, '文件传输失败')

        tar_cmd = f"cd {self.pkg_path};tar -xvf {file_name};ls {self.pkg_path};"
        self.log.info(tar_cmd)
        res = self.common.get_sh_result(self.pri_root_node, tar_cmd)
        self.assertIn('include', res, '文件解压失败')
        self.common.scp_file(self.pri_root_node, 'libpq_file.c', scp_path)

        self.log.info('-----修改脚本中内容-----')
        file_path = os.path.join(scp_path, 'libpq_file.c')
        sql_cmd = f"drop table if exists t_tinyblob_047;" \
                  f"create table t_tinyblob_047(field_name tinyblob, id int);" \
                  f"insert into t_tinyblob_047 values ('aaa', 1);"
        pwd = self.user_node.db_password
        sed_cmd = f'sed -i "s|host|localhost|g" {file_path};' \
            f'sed -i "s|db_port|{self.user_node.db_port}|g" {file_path};' \
            f'sed -i "s|db_name|{self.db_name}|g" {file_path};' \
            f'sed -i "s|user_name|{self.user_node.db_user}|g" {file_path};' \
            f'sed -i "s|password|{pwd}|g" {file_path};' \
            f'sed -i "s|sql_cmd|{sql_cmd}|g" {file_path};' \
            f'sed -i "s|table_name|t_tinyblob_047|g" {file_path};'
        self.log.info(sed_cmd)
        res = self.common.get_sh_result(self.pri_root_node, sed_cmd)
        self.assertEqual('', res, '参数替换失败')

        self.log.info('-----执行gcc命令运行lib驱动执行命令-----')
        lib_path = os.path.join(self.pkg_path, 'lib', 'libpq.so')
        gcc_out_file = os.path.join(scp_path, 'libpq_file')
        gcc_cmd = f"source {macro.DB_ENV_PATH};" \
                  f"gcc -c {file_path} -I {os.path.dirname(scp_path)};" \
                  f"gcc -o {gcc_out_file} libpq_file.o " \
                  f"{lib_path} -ldl;{gcc_out_file}"
        self.log.info(gcc_cmd)
        res = self.common.get_sh_result(self.pri_root_node, gcc_cmd)
        self.assertIn('616161', res, 'lib驱动执行失败')

    def tearDown(self):
        self.log.info('-----step4:清理环境; expect:成功-----')
        sql_cmd = f"drop database if exists {self.db_name};"
        self.log.info(sql_cmd)
        sql_res = sh_primary.execut_db_sql(sql_cmd, dbname='postgres')
        self.log.info(sql_res)
        rm_cmd = f"rm -rf {os.path.join(scp_path, 'libpq_file')};" \
                 f"rm -rf {os.path.join(scp_path, 'libpq_file.o')};" \
                 f"rm -rf {os.path.join(scp_path, 'libpq_file.c')};"
        self.log.info(rm_cmd)
        rm_msg = self.common.get_sh_result(self.pri_root_node, rm_cmd)
        self.assertIn('DROP DATABASE', sql_res, '数据库创建失败')
        self.assertEqual(len(rm_msg), 0, '文件删除失败')
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
